#pragma once

#include <assert.h>
#include <iostream>
#include <string>
#include <unordered_map>
#include <vector>
#include "../Common/Tool.hpp"
#include "../Common/Logger.hpp"

namespace OJ
{
  struct Question
  {
    int question_number;//题目编号
    std::string title;//题目标题
    std::string difficulty;//题目难度
    std::string description;//题目描述
    int cpu_limit;      // 时间限制,以秒为单位
    int memory_limit;   // 空间限制,以KB为单位
    std::string header; // 预设题头
    std::string tail;   // 测试用例代码
  };
  const std::string questions_path = "./questions/";
  const std::string questins_list = "./questions/questions.list";
  
  class Model
  {
  public:
    Model()
    {
      assert(loadQuestionsList(questins_list));
    }

    virtual ~Model() {}

  public:
    // 将文件列表中的题目加载进内存
    bool loadQuestionsList(const std::string &file_path)
    {
      std::ifstream ifs(file_path);
      if (!ifs.is_open())
      {
         ELOG("open file:%s failed\n",file_path.c_str());
        return false;
      }

      std::string line;
      while (std::getline(ifs, line))
      {
        std::vector<std::string> contects;

        Tool::StrHelper::split(line, " ",contects);
        if(contects.size() < 5)
        {
          ELOG("读取文件:%s 失败, 格式错误\n",file_path.c_str())
        }

        Question q;
        q.question_number = std::stoi(contects[0]);
        q.title = contects[1];
        q.difficulty = contects[2];
        q.cpu_limit = std::stoi(contects[3]);
        q.memory_limit = std::stoi(contects[4]);

        
        Tool::FileHandler::readFile(questions_path + std::to_string(q.question_number)+"/"+"desc.txt",q.description,true);
        Tool::FileHandler::readFile(questions_path + std::to_string(q.question_number)+"/"+"header.cpp",q.header,true);
        Tool::FileHandler::readFile(questions_path + std::to_string(q.question_number)+"/"+"tail.cpp" ,q.tail,true);

        _question.insert(std::make_pair(std::to_string(q.question_number),q));
      }
      DLOG("load questions list success\n");
      ifs.close();
      return true;
    }

    bool getAllQuestions(std::vector<Question>& out)
    {
      for(auto & q : _question)
      {
        out.push_back(q.second);
      }
      return true;
    }

    bool getQuestion(const int &number, Question& out)
    {
      auto it = _question.find(std::to_string(number));
      if(it == _question.end())
      {
        return false;
      }

      out = it->second;
      return true;
    }

  private:
    std::unordered_map<std::string, Question> _question;
  };
}